package com.le.tester.book.concurrentjavafight.l_8_4;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Logger;

/**
 * createTime：2022/12/29 13:44
 * description：ThreadPoolExecutor扩展
 */
public class TimingThreadPool extends ThreadPoolExecutor {
    private final ThreadLocal<Long> startTime = new ThreadLocal<>();

    private final Logger log = Logger.getAnonymousLogger("TimingThreadPool");

    private final AtomicLong numTasks = new AtomicLong();

    private final AtomicLong totalTimes = new AtomicLong();

    public TimingThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    protected void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        log.fine(String.format("Thread %s:start %s", t, r));
        startTime.set(System.nanoTime());
    }


    //try beforeExecute [sub try(task.run())->finally afterExecute],even if catch,still execute afterExecute
    protected void afterExecute(Runnable r, Throwable t) {
        try {
            long endTime = System.nanoTime();
            long durationTime = Math.subtractExact(startTime.get(), endTime);
            //final long
            numTasks.incrementAndGet();
            totalTimes.addAndGet(durationTime);
            log.fine(String.format("Thread %s:start %s", t, r));
        } finally {
            super.afterExecute(r, t);
        }

    }

    protected void terminated() {
        try {
            log.info("terminated");
        } finally {
            super.terminated();
        }
    }
}
